<!doctype HTML public "-//W3C//DTD HTML 4.0 Frameset//EN">
<html>
<title>Bloomberg Development Environment</title>
<html>
<pre>
// Copyright 2016-2023 Bloomberg Finance L.P.
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// bmqa_abstractsession.h                                             -*-C++-*-
#ifndef INCLUDED_BMQA_ABSTRACTSESSION
#define INCLUDED_BMQA_ABSTRACTSESSION

//@PURPOSE: Provide a pure protocol for a BlazingMQ session.
//
//@CLASSES:
//  bmqa::AbstractSession: Interface for a BlazingMQ session.
//
//@DESCRIPTION:
// &#39;bmqa::AbstractSession&#39; is a pure protocol for a BlazingMQ session.


// BMQ
#include &lt;bmqscm_version.h&gt;
#include &lt;bmqa_closequeuestatus.h&gt;
#include &lt;bmqa_configurequeuestatus.h&gt;
#include &lt;bmqa_confirmeventbuilder.h&gt;
#include &lt;bmqa_event.h&gt;
#include &lt;bmqa_messageeventbuilder.h&gt;
#include &lt;bmqa_messageproperties.h&gt;
#include &lt;bmqa_openqueuestatus.h&gt;
#include &lt;bmqa_queueid.h&gt;
#include &lt;bmqt_queueoptions.h&gt;
#include &lt;bmqt_uri.h&gt;

// BDE
#include &lt;bsl_functional.h&gt;
#include &lt;bsls_timeinterval.h&gt;
#include &lt;bsls_types.h&gt;

namespace BloombergLP {
namespace bmqa {

                           // =====================
                           // class AbstractSession
                           // =====================

class AbstractSession {
    // A pure protocol for a session.

  public:
    // TYPES
    typedef bsl::function&lt;void(const bmqa::OpenQueueStatus&amp; result)&gt;
                                                        OpenQueueCallback;
        // Invoked as a response to an asynchronous open queue operation,
        // &#39;OpenQueueCallback&#39; is an alias for a callback function object
        // (functor) that takes as an argument the specified &#39;result&#39;,
        // providing the result and context of the requested operation.

    typedef bsl::function&lt;void(const bmqa::ConfigureQueueStatus&amp; result)&gt;
                                                        ConfigureQueueCallback;
        // Invoked as a response to an asynchronous configure queue operation,
        // &#39;ConfigureQueueCallback&#39; is an alias for a callback function object
        // (functor) that takes as an argument the specified &#39;result&#39;,
        // providing the result and context of the requested operation.

    typedef bsl::function&lt;void(const bmqa::CloseQueueStatus&amp; result)&gt;
                                                        CloseQueueCallback;
        // Invoked as a response to an asynchronous close queue operation,
        // &#39;CloseQueueCallback&#39; is an alias for a callback function object
        // (functor) that takes as an argument the specified &#39;result&#39;,
        // providing the result and context of the requested operation.

  public:
    // CREATORS
    virtual
    ~AbstractSession();
        // Destructor

    // MANIPULATORS

    ///Session management
    ///------------------
    virtual
    int start(const bsls::TimeInterval&amp; timeout = bsls::TimeInterval());
        // Connect to the BlazingMQ broker and start the message processing for
        // this &#39;Session&#39;.  This method blocks until either the &#39;Session&#39; is
        // connected to the broker, fails to connect, or the operation times
        // out.  If the optionally specified &#39;timeout&#39; is not populated, use
        // the one defined in the session options.  Return 0 on success, or a
        // non-zero value corresponding to the &#39;bmqt::GenericResult::Enum&#39; enum
        // values otherwise.  The behavior is undefined if this method is
        // called on an already started &#39;Session&#39;.

    virtual
    int startAsync(const bsls::TimeInterval&amp; timeout = bsls::TimeInterval());
        // Connect to the BlazingMQ broker and start the message processing for
        // this &#39;Session&#39;.  This method returns without blocking.  The result
        // of the operation is communicated with a session event.  If the
        // optionally specified &#39;timeout&#39; is not populated, use the one defined
        // in the session options.  Return 0 on success (this doesn&#39;t imply the
        // session is connected !), or a non-zero value corresponding to the
        // &#39;bmqt::GenericResult::Enum&#39; enum values otherwise.  The behavior is
        // undefined if this method is called on an already started &#39;Session&#39;.

    virtual
    void stop();
        // Gracefully disconnect from the BlazingMQ broker and stop the
        // operation of this &#39;Session&#39;.  This method blocks waiting for all
        // already invoked event handlers to exit and all session-related
        // operations to be finished.  No other method but &#39;start()&#39; may be
        // used after this method returns.  This method must *NOT* be called if
        // the session is in synchronous mode (i.e., not using the
        // EventHandler), &#39;stopAsync()&#39; should be called in this case.

    virtual
    void stopAsync();
        // Disconnect from the BlazingMQ broker and stop the operation of this
        // &#39;Session&#39;.  This method returns without blocking and neither enforce
        // nor waits for any already started session-related operation to be
        // finished.  No method may be used after this method returns.

    virtual
    void finalizeStop();
        // **DEPRECATED**
        //
        // This method is only to be used if the session is in synchronous mode
        // (i.e., not using the EventHandler): it must be called once all
        // threads getting events with &#39;nextEvent()&#39; have been joined.

    virtual
    void loadMessageEventBuilder(MessageEventBuilder *builder);
        // Load into the specified &#39;builder&#39; an instance of
        // &#39;bmqa::MessageEventBuilder&#39; that can be used to build message event
        // for posting on this session.  The behavior is undefined unless the
        // session has been successfully started and &#39;builder&#39; is non-null.
        // Note that lifetime of the loaded object is bound by the lifetime of
        // this session instance (i.e., loaded instance cannot outlive this
        // session instance).  Also note that the &#39;MessageEventBuilder&#39; objects
        // are pooled, so this operation is cheap, and &#39;MessageEventBuilder&#39;
        // can be obtained on demand and kept on the stack.

    virtual
    void loadConfirmEventBuilder(ConfirmEventBuilder *builder);
        // Load into the specified &#39;builder&#39; an instance of
        // &#39;bmqa::ConfirmEventBuilder&#39; that can be used to build a batch of
        // CONFIRM messages for sending to the broker.  The behavior is
        // undefined unless the session has been successfully started and
        // &#39;builder&#39; is non-null.  Note that the lifetime of the loaded object
        // is bound by the lifetime of this session instance (i.e., loaded
        // instance cannot outlive this session instance).

    virtual
    void loadMessageProperties(MessageProperties *buffer);
        // Load into the specified &#39;buffer&#39; an instance of &#39;MessageProperties&#39;
        // that can be used to specify and associate properties while building
        // a &#39;bmqa::Message&#39;.  The behavior is undefined unless the session has
        // been successfully started and &#39;buffer&#39; is non-null.  Note that
        // lifetime of the loaded object is bound by the lifetime of this
        // session instance (i.e., loaded instance cannot outlive this session
        // instance).

    ///Queue management
    ///----------------
    virtual
    int getQueueId(QueueId          *queueId,
                   const bmqt::Uri&amp;  uri) const;
        // Load in the specified &#39;queueId&#39; the queue corresponding to the
        // specified &#39;uri&#39; and return 0 if such a queue was found, or leave
        // &#39;queueId&#39; untouched and return a non-zero value if no queue
        // corresponding to &#39;uri&#39; is currently open.

    virtual
    int getQueueId(QueueId                    *queueId,
                   const bmqt::CorrelationId&amp;  correlationId) const;
        // Load in the specified &#39;queueId&#39; the queue corresponding to the
        // specified &#39;correlationId&#39; and return 0 if such a queue was found, or
        // leave &#39;queueId&#39; untouched and return a non-zero value if no queue
        // corresponding to &#39;correlationId&#39; is currently open.

    virtual
    int
    openQueue(QueueId                   *queueId,
              const bmqt::Uri&amp;           uri,
              bsls::Types::Uint64        flags,
              const bmqt::QueueOptions&amp;  options = bmqt::QueueOptions(),
              const bsls::TimeInterval&amp;  timeout = bsls::TimeInterval());
        // DEPRECATED: Use the &#39;openQueueSync(QueueId *queueId...)&#39; instead.
        //             This method will be marked as
        //             &#39;BSLS_ANNOTATION_DEPRECATED&#39; in future release of
        //             libbmq.

    virtual
    OpenQueueStatus
    openQueueSync(QueueId                   *queueId,
                  const bmqt::Uri&amp;           uri,
                  bsls::Types::Uint64        flags,
                  const bmqt::QueueOptions&amp;  options = bmqt::QueueOptions(),
                  const bsls::TimeInterval&amp;  timeout = bsls::TimeInterval());
        // Open the queue having the specified &#39;uri&#39; with the specified &#39;flags&#39;
        // (a combination of the values defined in &#39;bmqt::QueueFlags::Enum&#39;),
        // using the specified &#39;queueId&#39; to correlate events related to that
        // queue.  The object &#39;queueId&#39; referring to is modified, so the
        // &#39;queueId&#39; represents the actual queue uri, flags and options.
        // Return a result providing the status and context of the operation.
        // Use the optionally specified &#39;options&#39; to configure some advanced
        // settings.  Note that this operation fails if &#39;queueId&#39; is
        // non-unique.  If the optionally specified &#39;timeout&#39; is not populated,
        // use the one defined in the session options.  This operation will
        // block until either success, failure, or timing out happens.
        //
        // THREAD: Note that calling this method from the event processing
        //         thread(s) (i.e., from the EventHandler callback, if
        //         provided) *WILL* lead to a *DEADLOCK*.

    virtual
    int
    openQueueAsync(QueueId                   *queueId,
                   const bmqt::Uri&amp;           uri,
                   bsls::Types::Uint64        flags,
                   const bmqt::QueueOptions&amp;  options = bmqt::QueueOptions(),
                   const bsls::TimeInterval&amp;  timeout = bsls::TimeInterval());
        // DEPRECATED: Use the &#39;openQueueAsync(...)&#39; with callback flavor
        //             instead.  This method will be marked as
        //             &#39;BSLS_ANNOTATION_DEPRECATED&#39; in future release of
        //             libbmq.

    virtual
    void
    openQueueAsync(bmqa::QueueId             *queueId,
                   const bmqt::Uri&amp;           uri,
                   bsls::Types::Uint64        flags,
                   const OpenQueueCallback&amp;   callback,
                   const bmqt::QueueOptions&amp;  options  = bmqt::QueueOptions(),
                   const bsls::TimeInterval&amp;  timeout  = bsls::TimeInterval());
        // Asynchronously open the queue having the specified &#39;uri&#39; with the
        // specified &#39;flags&#39; (a combination of the values defined in
        // &#39;bmqt::QueueFlags::Enum&#39;), using the specified &#39;queueId&#39; to
        // correlate events related to that queue and the optionally specified
        // &#39;options&#39; to configure some advanced settings.  The object &#39;queueId&#39;
        // referring to is modified, so the &#39;queueId&#39; represents the actual
        // queue uri, flags and options.  The result of the operation is
        // communicated to the specified &#39;callback&#39; via a
        // &#39;bmqa::OpenQueueStatus&#39;, providing the status and context of the
        // requested operation.  Note that this operation fails if &#39;queueId&#39; is
        // non-unique.  If the optionally specified &#39;timeout&#39; is not populated,
        // use the one defined in the session options.
        //
        // THREAD: The &#39;callback&#39; will *ALWAYS* be invoked from the
        //         EventHandler thread(s) (or if a SessionEventHandler was not
        //         specified, from the thread invoking &#39;nextEvent&#39;).

    virtual
    int
    configureQueue(QueueId                   *queueId,
                   const bmqt::QueueOptions&amp;  options,
                   const bsls::TimeInterval&amp;  timeout = bsls::TimeInterval());
        // DEPRECATED: Use the &#39;configureQueueSync(QueueId *queueId...)
        //             instead.  This method will be marked as
        //             &#39;BSLS_ANNOTATION_DEPRECATED&#39; in future release of
        //             libbmq.

    virtual
    ConfigureQueueStatus
    configureQueueSync(
                    const QueueId             *queueId,
                    const bmqt::QueueOptions&amp;  options,
                    const bsls::TimeInterval&amp;  timeout = bsls::TimeInterval());
        // Configure the queue identified by the specified &#39;queueId&#39; using the
        // specified &#39;options&#39; and return a result providing the status and
        // context of the operation.  Fields from &#39;options&#39; that have not been
        // explicitly set will not be modified.  If the optionally specified
        // &#39;timeout&#39; is not populated, use the one defined in the session
        // options.  This operation returns error if there is a pending
        // configure for the same queue.  This operation will block until
        // either success, failure, or timing out happens.
        //
        // THREAD: Note that calling this method from the event processing
        //         thread(s) (i.e., from the EventHandler callback, if
        //         provided) *WILL* lead to a *DEADLOCK*.

    virtual
    int
    configureQueueAsync(
                    QueueId                   *queueId,
                    const bmqt::QueueOptions&amp;  options,
                    const bsls::TimeInterval&amp;  timeout = bsls::TimeInterval());
        // DEPRECATED: Use the &#39;configureQueueAsync(...)&#39; with callback flavor
        //             instead.  This method will be marked as
        //             &#39;BSLS_ANNOTATION_DEPRECATED&#39; in future release of
        //             libbmq.

    virtual
    void configureQueueAsync(
               const QueueId                 *queueId,
               const bmqt::QueueOptions&amp;      options,
               const ConfigureQueueCallback&amp;  callback,
               const bsls::TimeInterval&amp;      timeout  = bsls::TimeInterval());

        // Asynchronously configure the queue identified by the specified
        // &#39;queueId&#39; using the specified &#39;options&#39; to configure some advanced
        // settings.  The result of the operation is communicated to the
        // specified &#39;callback&#39; via a &#39;bmqa::ConfigureQueueStatus&#39;, providing
        // the status and context of the requested operation.  If the
        // optionally specified &#39;timeout&#39; is not populated, use the one defined
        // in the session options.
        //
        // THREAD: The &#39;callback&#39; will *ALWAYS* be invoked from the
        //         EventHandler thread(s) (or if a SessionEventHandler was not
        //         specified, from the thread invoking &#39;nextEvent&#39;).

    virtual
    int
    closeQueue(QueueId                   *queueId,
               const bsls::TimeInterval&amp;  timeout = bsls::TimeInterval());
        // DEPRECATED: Use the &#39;closeQueueSync(QueueId *queueId...) instead.
        //             This method will be marked as
        //             &#39;BSLS_ANNOTATION_DEPRECATED&#39; in future release of
        //             libbmq.

    virtual
    CloseQueueStatus
    closeQueueSync(const QueueId             *queueId,
                   const bsls::TimeInterval&amp;  timeout = bsls::TimeInterval());
        // Close the queue identified by the specified &#39;queueId&#39; and return a
        // result providing the status and context of the operation.  If the
        // optionally specified &#39;timeout&#39; is not populated, use the one defined
        // in the session options.  Any outstanding configureQueue request for
        // this &#39;queueId&#39; will be canceled.  This operation will block until
        // either success, failure, or timing out happens.  Once this method
        // returns, there is guarantee that no more messages and events for
        // this &#39;queueId&#39; will be received.  Note that successful processing of
        // this request in the broker closes this session&#39;s view of the queue;
        // the underlying queue may not be deleted in the broker.  When this
        // method returns, the correlationId associated to the queue is
        // cleared.
        //
        // THREAD: Note that calling this method from the event processing
        //         thread(s) (i.e., from the EventHandler callback, if
        //         provided) *WILL* lead to a *DEADLOCK*.

    virtual
    int
    closeQueueAsync(QueueId                   *queueId,
                    const bsls::TimeInterval&amp;  timeout = bsls::TimeInterval());
        // DEPRECATED: Use the &#39;closeQueueAsync(...)&#39; with callback flavor
        //             instead.  This method will be marked as
        //             &#39;BSLS_ANNOTATION_DEPRECATED&#39; in future release of
        //             libbmq.

    virtual
    void closeQueueAsync(
                   const QueueId             *queueId,
                   const CloseQueueCallback&amp;  callback,
                   const bsls::TimeInterval&amp;  timeout  = bsls::TimeInterval());
        // Asynchronously close the queue identified by the specified
        // &#39;queueId&#39;.  Any outstanding configureQueue requests will be
        // canceled.  The result of the operation is communicated to the
        // specified &#39;callback&#39; via a &#39;bmqa::CloseQueueStatus&#39;, providing the
        // status and context of the operation.  If the optionally specified
        // &#39;timeout&#39; is not populated, use the one defined in the session
        // options.  Note that successful processing of this request in the
        // broker closes this session&#39;s view of the queue; the underlying queue
        // may not be deleted in the broker.  The correlationId associated to
        // the queue remains valid until the &#39;bmqa::CloseQueueStatus&#39; result
        // has been received and processed by the &#39;callback&#39;, after which it
        // will be cleared and no more messages and events for this &#39;queueId&#39;
        // will be received.
        //
        // THREAD: The &#39;callback&#39; will *ALWAYS* be invoked from the
        //         EventHandler thread(s) (or if a SessionEventHandler was not
        //         specified, from the thread invoking &#39;nextEvent&#39;).

    ///Queue manipulation
    ///------------------
    virtual
    Event nextEvent(const bsls::TimeInterval&amp; timeout = bsls::TimeInterval());
        // Return the next available event received for this session.  If there
        // is no event available, this method blocks for up to the optionally
        // specified &#39;timeout&#39; time interval for an event to arrive.  An empty
        // time interval for &#39;timeout&#39; (the default) indicates that the method
        // should not timeout (the method will not return until the next event
        // is available).  Return a &#39;bmqa::SessionEvent&#39; of type
        // &#39;bmqt::SessionEventType::e_TIMEOUT&#39; if a timeout was specified and
        // that timeout expired before any event was received.  Note that this
        // method can only be used if the session is in synchronous mode (ie
        // not using the EventHandler).  The behavior is undefined unless the
        // session was started.

    virtual
    int post(const MessageEvent&amp; event);
        // Asynchronously post the specified &#39;event&#39; that must contain one or
        // more &#39;Messages&#39;.  The return value is one of the values defined in
        // the &#39;bmqt::PostResult::Enum&#39; enum.  Return zero on success and a
        // non-zero value otherwise.  Note that success implies that SDK has
        // accepted the &#39;event&#39; and will eventually deliver it to the broker.
        // The behavior is undefined unless the session was started.

    virtual
    int confirmMessage(const Message&amp; message);
        // Asynchronously confirm the receipt of the specified &#39;message&#39;.  This
        // indicates that the application is done processing the message and
        // that the broker can safely discard it from the queue according to
        // the retention policy set up for that queue.  Return 0 on success,
        // and a non-zero value otherwise.  Note that success implies that SDK
        // has accepted the &#39;message&#39; and will eventually send confirmation
        // notification to the broker.

    virtual
    int confirmMessage(const MessageConfirmationCookie&amp; cookie);
        // Asynchronously confirm the receipt of the message with which the
        // specified &#39;cookie&#39; is associated.  This indicates that the
        // application is done processing the message and that the broker can
        // safely discard it from the queue according to the retention policy
        // set up for that queue.  Return 0 on success, and a non-zero value
        // otherwise.  Note that success implies that SDK has accepted the
        // &#39;message&#39; and will eventually send confirmation notification to the
        // broker.

    virtual
    int confirmMessages(ConfirmEventBuilder *builder);
        // Asynchronously confirm the receipt of the batch of CONFIRM messages
        // contained in the specified &#39;builder&#39;.  This indicates that the
        // application is done processing all of the messages and that the
        // broker can safely discard them from the queue according to the
        // retention policy set up for that queue.  Return 0 on success, and a
        // non-zero value otherwise.  Note that in case of success, the
        // instance pointed by the &#39;builder&#39; will be reset.  Also note that
        // success implies that SDK has accepted all of the messages in
        // &#39;builder&#39; and will eventually send confirmation notification to the
        // broker.  Behavior is undefined unless &#39;builder&#39; is non-null.

    ///Debugging related
    ///-----------------
    virtual
    int configureMessageDumping(const bslstl::StringRef&amp; command);
        // Configure this session instance to dump messages to the installed
        // logger at &#39;ball::Severity::INFO&#39; level according to the specified
        // &#39;command&#39; that should adhere to the following pattern:
        //..
        //   IN|OUT ON|OFF|100|10s
        //..
        // where each token has a specific meaning:
        //: o !IN!  : incoming (&#39;PUSH&#39; and &#39;ACK&#39;) events
        //: o !OUT! : outgoing (&#39;PUT&#39; and &#39;CONFIRM&#39;) events
        //: o !ON!  : turn on message dumping until explicitly turned off
        //: o !OFF! : turn off message dumping
        //: o !100! : turn on message dumping for the next 100 messages
        //: o !10s! : turn on message dumping for the next 10 seconds
        // Note that above, &#39;100&#39; and &#39;10&#39; numerical values are for just for
        // illustration purposes, and application can choose an appropriate
        // value for them.  Also note that pattern is case-insensitive.  Return
        // zero if &#39;command&#39; is valid and message dumping has been configured,
        // non-zero value otherwise.  The behavior is undefined unless the
        // session has been started.
};

}  // close package namespace
}  // close enterprise namespace

#endif
</pre>
</body>
</html>
